home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 23
/
CU Amiga - Super CD-ROM 23 (June 1998).iso
/
CUCD
/
Online
/
AMarquee
/
examples
/
AMarqueeDebugMultiThread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-20
|
10KB
|
247 lines
/* This version of AMarqueeDebug creates the QSession, then
spawns a child thread and hands control of the QSession
to the child thread via QDetachSession() and QReattachSession().
There aren't any advantages to doing it this way, except
to show how (and that ;)) QDetachSession() and QReattachSession()
work.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/AMarquee_protos.h>
#include <pragmas/AMarquee_pragmas.h>
#include "include:signal.h"
struct Library * AMarqueeBase = NULL;
struct QSession * session = NULL;
BOOL waitForChildThread = TRUE;
/* Takes user input until blank line is typed */
void ProcessDebugCommands(struct QSession * session)
{
while(1)
{
char debugline[500] = "\0\0\0\0\0\0\0\0";
char * keyword, * data;
ULONG dataLen = 0L;
LONG res;
printf("Enter your debug command now: "); fflush(stdout);
gets(debugline);
keyword = &debugline[2];
if (data = strchr(keyword,'='))
{
*data = '\0'; /* terminate the keyword */
data++;
dataLen = strlen(data)+1;
}
switch((int)(debugline[0]))
{
case '\0': res=QGo(session,0L); break;
case 'A': res=QSetMessageAccessOp(session, keyword, -1); break;
case 'm': res=QMessageOp(session, keyword, data, dataLen); break;
case 'M': res=QSysMessageOp(session, keyword, data); break;
case 'a': res=QSetAccessOp(session, keyword); break;
case 's': res=QSetOp(session, keyword, data, dataLen); break;
case 'S': res=QStreamOp(session, keyword, data, dataLen); break;
case 'r': res=QRenameOp(session, keyword, data); break;
case 'D': res=QDebugOp(session, keyword); break;
case 'g': res=QGetOp(session, keyword, -1); break;
case 'd': res=QDeleteOp(session, keyword); break;
case 'i': res=QInfoOp(session); break;
case 'c': res=QSubscribeOp(session, keyword, -1); break;
case 'C': res=QGetAndSubscribeOp(session, keyword, -1); break;
case 'k': res=QClearSubscriptionsOp(session,atoi(keyword)); break;
case 'p': res=QPingOp(session); break;
case 'v': res=QRequestPrivilegesOp(session,atol(keyword)); break;
case 'w': res=QReleasePrivilegesOp(session,atol(keyword)); break;
case '!': res=QKillClientsOp(session,keyword); break;
case '?': res=QGetParameterOp(session,keyword); break;
case '$': res=QSetParameterOp(session,keyword,data); break;
default: printf("Command code %c was not recognized.\n",debugline[0]); break;
}
printf("(Op result was %i)\n",res);
if (debugline[0] == '\0') return;
}
}
__geta4 void ChildThreadEntryFunc(void)
{
if (QReattachSession(session, 0L) == FALSE) printf("Error: QReattachSession failed! Press CTRL-C to exit.\n");
else
{
printf("Child thread is running!\n");
while(1)
{
struct QMessage * qMsg;
ULONG signals = (1L << session->qMsgPort->mp_SigBit) | (SIGBREAKF_CTRL_C) | (SIGBREAKF_CTRL_F);
/* Wait for next message from the server */
signals = Wait(signals);
if (signals & (1L << session->qMsgPort->mp_SigBit))
{
while(qMsg = (struct QMessage *) GetMsg(session->qMsgPort))
{
struct QRunInfo * inf = (qMsg->qm_DataLen == sizeof(struct QRunInfo)) ? ((struct QRunInfo *) qMsg->qm_Data) : NULL;
/* Handle message */
printf("Message %p recieved---------\n",qMsg);
printf("Status: %i (%s)\n", qMsg->qm_Status, QErrorName(qMsg->qm_Status));
printf("Error Line: %i\n", qMsg->qm_ErrorLine);
printf("Message ID: %i\n", qMsg->qm_ID);
printf("Path: [%s]\n", qMsg->qm_Path?qMsg->qm_Path:"<NULL>");
printf("Data: [%s](int=%i)\n", qMsg->qm_Data?qMsg->qm_Data:((UBYTE*)"<NULL>"),qMsg->qm_Data?(*((int*)qMsg->qm_Data)):0);
printf("DataLen: %lu\n", qMsg->qm_DataLen);
printf("ActualLen: %lu\n", qMsg->qm_ActualLen);
if (inf) printf("Info: alloced:%li allowed:%li avail:%li curPrivs=0x%x posPrivs=0x%x\n",
inf->qr_Alloced, inf->qr_Allowed, inf->qr_Avail, inf->qr_CurrentPrivs, inf->qr_PossiblePrivs);
FreeQMessage(session, qMsg);
}
}
if (signals & SIGBREAKF_CTRL_F) ProcessDebugCommands(session);
if (signals & SIGBREAKF_CTRL_C) break; /* Quit if CTRL-C pressed */
}
#ifdef LET_CHILD_THREAD_FREE_THE_QSESSION
printf("Freeing QSession in child thread...\n");
QFreeSession(session);
session = NULL; /* So that the main thread won't try to free it */
#else
if (QDetachSession(session, 0L) == FALSE) printf("Warning: Child's QDetachSession failed!\n");
/* Now the main thread is able to free the QSession. */
#endif
}
printf("Child thread is exiting...\n");
/* Signals main thread to wake up... hacky method but it's just for this test proggy */
Forbid(); /* to make sure our thread has died before the code gets unloaded! */
waitForChildThread = FALSE;
}
/* Main program */
int main(int argc, char ** argv)
{
char * connectTo, * progName;
int port;
printf("Usage Note: AMarqueeDebugMultiThread [hostname=localhost] [myname=debug] [port=2957]\n");
signal(SIGINT, SIG_IGN); /* Don't let DICE abort us abruptly */
connectTo = (argc>1) ? argv[1] : "localhost";
progName = (argc>2) ? argv[2] : "debug";
port = (argc>3) ? atoi(argv[3]) : 2957;
if ((AMarqueeBase = OpenLibrary("amarquee.library",47L)) == NULL)
{
printf("Couldn't open amarquee.library v47!\n");
exit(RETURN_ERROR);
}
printf("Connecting to %s:%i (allocating QSession in main thread)\n",connectTo, port);
if ((session = QNewSession(connectTo, port, progName)) == NULL)
{
printf("Couldn't connect to server %s:%i\n",connectTo, port);
exit(RETURN_WARN);
}
printf("Connected to server %s:%i\n",connectTo, port);
/* Setup some sample data */
(void)QSetOp(session, "sampledata", "Kids", 5);
(void)QSetOp(session, "sampledata/Jeremy", "1", 2);
(void)QSetOp(session, "sampledata/Joanna", "2", 2);
(void)QSetOp(session, "sampledata/Joanna/nerd", "yep! :)", 8);
(void)QSetOp(session, "sampledata/Joellen", "3", 2);
(void)QSetOp(session, "sampledata/Charcoal", "Kitty!", 7);
(void)QGetOp(session, "/#?/#?/#?/#?", -1);
(void)QGo(session, 0L);
printf("Commands are:\n");
printf("\n");
printf("a wildhostpath Access control (default is /#?/#?)\n");
printf("A wildhostpath Access control for incoming messages (default in no access)\n");
printf("m hosts=data Send an active message to hosts\n");
printf("M hosts=string Send an system message to hosts\n");
printf("s path=data Set data node value\n");
printf("S path=data Stream data node value\n");
printf("r path=newlabel Rename data node\n");
printf("D debugstring Send debug string\n");
printf("g wildpath Get a node or nodes\n");
printf("c wildpath Subscribe to a node or nodes\n");
printf("C wildpath Get&Subscribe to a node or nodes\n");
printf("k opID Klear subscriptions (by id or 0 for all)\n");
printf("d wildpath Delete a node or nodes\n");
printf("i Request info packet\n");
printf("p Request ping packet\n");
printf("v # Request new privileges (by code bitchord)\n");
printf("w # Release existing privileges (by code bitchord)\n");
printf("! hosts Kill other clients (requires KILLCLIENTS privilege!)\n");
printf("$ param=string Set a parameter with QSetParam()\n");
printf("? param Get a parameter by name\n");
printf("<enter> Send accumulated transactions (GO!!)\n");
printf("\n");
printf("Press CTRL-F to enter commands, or CTRL-C to quit\n");
if (QDetachSession(session, 0L)) /* Make the QSession available to other threads */
{
struct Task * childThread;
printf("Spawning child thread...\n");
if (childThread = CreateNewProcTags(NP_Entry, ChildThreadEntryFunc, NP_Name, "AMarqueeDebugMultiThread Child Process", TAG_END, NULL))
{
BOOL childGone = FALSE;
while(1)
{
ULONG sigs = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F);
if (sigs & SIGBREAKF_CTRL_C)
{
break;
}
if (sigs & SIGBREAKF_CTRL_F) Signal(childThread, SIGBREAKF_CTRL_F);
}
printf("Main thread is waiting for child thread to die now.\n");
while(childGone == FALSE)
{
Delay(10);
Forbid();
if (waitForChildThread) Signal(childThread, SIGBREAKF_CTRL_C);
else childGone = TRUE;
Permit();
}
}
}
else printf("Error, couldn't Detach QSession from main thread\n");
printf("\nCleaning up...\n");
if (session)
{
printf("Main thread is freeing the QSession.\n");
/* This MUST be done before we close the library.
Furthermore, it must be done by the thread
the Qsession is attached to (it can be done by any
thread if the QSession is detached) */
QFreeSession(session);
}
if (AMarqueeBase) CloseLibrary(AMarqueeBase);
printf("All done.\n");
return(0);
}